package com.mdd.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mdd.admin.LikeAdminThreadLocal;
import com.mdd.admin.service.ICustomerProjectService;
import com.mdd.admin.validate.commons.PageValidate;
import com.mdd.admin.service.ICustomerMianService;
import com.mdd.admin.validate.customer.CustomerMianCreateValidate;
import com.mdd.admin.validate.customer.CustomerMianMatchingSearchValidate;
import com.mdd.admin.validate.customer.CustomerMianUpdateValidate;
import com.mdd.admin.validate.customer.CustomerMianSearchValidate;
import com.mdd.admin.vo.customer.CustomerMianListedVo;
import com.mdd.admin.vo.customer.CustomerMianDetailVo;
import com.mdd.admin.vo.customer.CustomerMianMatchingVo;
import com.mdd.common.core.PageResult;
import com.mdd.common.entity.ClientCrmProjetDetail;
import com.mdd.common.entity.CustomerDetail;
import com.mdd.common.entity.CustomerMian;
import com.mdd.common.entity.TDeclarationMatching;
import com.mdd.common.mapper.*;
import com.mdd.common.util.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 客户主表服务实现类
 * <p>
 * 该类负责处理客户主表(CustomerMian)相关的业务逻辑，包括：
 * - 客户信息的增删改查
 * - 客户详情的关联处理
 * - 客户与项目的匹配度评估
 * - 客户星级评定
 * </p>
 *
 * @author Jiejie
 */
@Slf4j
@Service
public class CustomerMianServiceImpl implements ICustomerMianService {

    @Resource
    CustomerMianMapper customerMianMapper;
    @Resource
    CustomerDetailMapper customerDetailMapper;

    @Resource
    ClientCrmProjetDetailMapper clientCrmProjetDetailMapper;

    @Resource
    TDeclarationMatchingMapper tDeclarationMatchingMapper;
    @Resource
    ClientCrmProjetDetailTypeMapper clientCrmProjetDetailTypeMapper;

    @Resource
    ICustomerProjectService customerProjectService;

    /**
     * 获取客户主表分页列表
     * <p>
     * 该方法实现以下功能：
     * 1. 支持多条件组合查询
     * 2. 支持分页查询
     * 3. 自动关联查询客户详情信息
     * 4. 转换时间戳为格式化日期
     * </p>
     *
     * @param pageValidate   分页参数，包含页码和每页数量
     * @param searchValidate 搜索条件参数，支持客户编码、名称、公司等多个维度搜索
     * @return PageResult<CustomerMianListedVo> 分页结果，包含客户列表数据
     * @author Jiejie
     */
    @Override
    public PageResult<CustomerMianListedVo> list(PageValidate pageValidate, CustomerMianSearchValidate searchValidate) {
        Integer page = pageValidate.getPageNo();
        Integer limit = pageValidate.getPageSize();

        QueryWrapper<CustomerMian> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", 0);
        queryWrapper.orderByDesc("id");

        customerMianMapper.setSearch(queryWrapper, searchValidate, new String[]{
                "=:code:str",
                "like:name:str",
                "=:subordinateCompanies@subordinate_companies:str",
                "=:department:str",
                "=:servicer:str",
                "=:supportStaff@support_staff:str",
                "=:registrationDate@registration_date:str",
                "=:registeredFund@registered_fund:str",
                "=:registeredType@registered_type:str",
                "=:technosphere:str",
                "like:companyName@company_name:str",
                "=:clientGrade@client_grade:str",
        });

        IPage<CustomerMian> iPage = customerMianMapper.selectPage(new Page<>(page, limit), queryWrapper);

        List<CustomerMianListedVo> list = new LinkedList<>();
        for (CustomerMian item : iPage.getRecords()) {
            CustomerMianListedVo vo = new CustomerMianListedVo();
            BeanUtils.copyProperties(item, vo);
            vo.setCreateTime(TimeUtils.timestampToDate(item.getCreateTime()));
//            if(item.getUpdateTime()!=""&& item.getUpdateTime()!=""){
//                vo.setUpdateTime(TimeUtils.timestampToDate(item.getUpdateTime()));
//            }
            QueryWrapper<CustomerDetail> detailQueryWrapper = new QueryWrapper<>();
            detailQueryWrapper.eq("mian_id", item.getId());
            log.info("detail{}", item.getId());
            CustomerDetail detail = customerDetailMapper.selectOne(detailQueryWrapper);
            vo.setDetail(detail);
            list.add(vo);
        }
        return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list);
    }

    /**
     * 获取所有客户列表（不分页）
     * <p>
     * 该方法实现以下功能：
     * 1. 支持多条件组合查询
     * 2. 自动关联查询客户详情信息
     * 3. 转换时间戳为标准日期格式
     * </p>
     *
     * @param searchValidate 搜索条件参数
     * @return List<CustomerMianListedVo> 客户列表数据
     */
    @Override
    public List<CustomerMianListedVo> all(CustomerMianSearchValidate searchValidate) {
        QueryWrapper<CustomerMian> queryWrapper = new QueryWrapper<CustomerMian>()
                .eq("is_delete", 0)
                .orderByDesc("id");

        customerMianMapper.setSearch(queryWrapper, searchValidate, new String[]{
                "=:code:str",
                "like:name:str",
                "=:subordinateCompanies@subordinate_companies:str",
                "=:department:str",
                "=:servicer:str",
                "=:supportStaff@support_staff:str",
                "=:registrationDate@registration_date:str",
                "=:registeredFund@registered_fund:str",
                "=:registeredType@registered_type:str",
                "=:technosphere:str",
                "like:companyName@company_name:str",
                "=:clientGrade@client_grade:str",
        });

        return customerMianMapper.selectList(queryWrapper).stream()
                .map(item -> {
                    CustomerMianListedVo vo = new CustomerMianListedVo();
                    cn.hutool.core.bean.BeanUtil.copyProperties(item, vo);
                    vo.setCreateTime(cn.hutool.core.date.DateUtil.format(
                            new Date(Long.parseLong(item.getCreateTime()) * 1000),
                            "yyyy-MM-dd HH:mm:ss"
                    ));
                    
                    CustomerDetail detail = customerDetailMapper.selectOne(
                            new QueryWrapper<CustomerDetail>().eq("mian_id", item.getId())
                    );
                    vo.setDetail(detail);
                    return vo;
                })
                .collect(Collectors.toList());
    }

    /**
     * 获取客户主表详情信息
     * <p>
     * 该方法实现以下功能：
     * 1. 根据ID查询客户主表记录
     * 2. 验证数据是否存在
     * 3. 关联查询客户详情信息
     * 4. 组装并返回完整的客户信息
     * </p>
     *
     * @param id 客户主表ID
     * @return CustomerMianDetailVo 客户详细信息，包含主表和详情表数据
     * @throws IllegalArgumentException 当客户数据不存在时抛出
     * @author Jiejie
     */
    @Override
    public CustomerMianDetailVo detail(Integer id) {
        CustomerMian model = customerMianMapper.selectOne(
                new QueryWrapper<CustomerMian>()
                        .eq("id", id)
                        .eq("is_delete", 0)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在");
        CustomerDetail detail = customerDetailMapper.selectOne(
                new QueryWrapper<CustomerDetail>()
                        .eq("mian_id", id)
                        .eq("is_delete", 0)
                        .last("limit 1"));
        CustomerMianDetailVo vo = new CustomerMianDetailVo();
        vo.setDetail(detail);
        BeanUtils.copyProperties(model, vo);
        return vo;
    }

    /**
     * 新增客户信息
     * <p>
     * 该方法实现以下功能：
     * 1. 创建并填充客户主表数据
     * 2. 设置创建者信息和时间戳
     * 3. 保存客户主表数据
     * 4. 关联保存客户详情数据
     * 5. 触发客户项目匹配度评估
     * </p>
     *
     * @param createValidate 客户创建参数，包含主表和详情表的数据
     * @return CustomerMian 新创建的客户实体
     * @author Jiejie
     */
    @Override
    public CustomerMian add(CustomerMianCreateValidate createValidate) {
        // 1. 创建并填充客户主表数据
        CustomerMian model = new CustomerMian();
        cn.hutool.core.bean.BeanUtil.copyProperties(createValidate, model);
        
        // 2. 设置创建者信息和时间
        model.setUserId(LikeAdminThreadLocal.getAdminId());
        model.setUserName(LikeAdminThreadLocal.get("username").toString());
        model.setCreateTime(String.valueOf(cn.hutool.core.date.DateUtil.currentSeconds()));
        model.setIsDelete(0);
        
        // 3. 保存客户主表数据
        customerMianMapper.insert(model);

        // 4. 设置并保存客户详情数据
        CustomerDetail detail = createValidate.getDetail();
        detail.setMianId(model.getId());
        detail.setIsDelete(0);
        detail.setUserId(LikeAdminThreadLocal.getAdminId());
        detail.setUserName(LikeAdminThreadLocal.get("username").toString());
        detail.setCreateTime(String.valueOf(cn.hutool.core.date.DateUtil.currentSeconds()));
        customerDetailMapper.insert(detail);

        // 5. 触发匹配存储过程
        clientCrmProjetDetailTypeMapper.callMatchingProcedure();
        return model;
    }

    /**
     * 客户主表编辑
     * 该方法实现以下功能：
     * 1. 根据ID查询并验证客户主表记录是否存在
     * 2. 使用Hutool工具类完成属性拷贝
     * 3. 更新客户主表信息
     * 4. 更新关联的客户详情信息
     * 5. 触发匹配存储过程进行数据更新
     *
     * @param updateValidate 客户主表更新参数，包含主表和详情表的更新数据
     * @throws IllegalArgumentException 当客户数据不存在时抛出
     * @author Jiejie
     */
    @Override
    public void edit(CustomerMianUpdateValidate updateValidate) {
        // 1. 查询并验证客户数据
        CustomerMian model = Optional.ofNullable(customerMianMapper.selectOne(
                new QueryWrapper<CustomerMian>()
                        .eq("id", updateValidate.getId())
                        .eq("is_delete", 0)
                        .last("limit 1")))
                .orElseThrow(() -> new IllegalArgumentException("数据不存在!"));

        // 2. 使用Hutool BeanUtil拷贝更新属性
        cn.hutool.core.bean.BeanUtil.copyProperties(updateValidate, model, "id", "isDelete", "createTime", "deleteTime");
        
        // 3. 设置更新者信息和时间
        model.setUpdateUserId(LikeAdminThreadLocal.getAdminId());
        model.setUpdateUserName(LikeAdminThreadLocal.get("username").toString());
        model.setUpdateTime(String.valueOf(cn.hutool.core.date.DateUtil.currentSeconds()));
        
        // 4. 更新客户主表
        customerMianMapper.updateById(model);

        // 5. 更新客户详情表
        CustomerDetail detail = updateValidate.getDetail();
        detail.setMianId(model.getId());
        detail.setUpdateId(LikeAdminThreadLocal.getAdminId());
        detail.setUpdateName(LikeAdminThreadLocal.get("username").toString());
        detail.setUpdateTime(String.valueOf(cn.hutool.core.date.DateUtil.currentSeconds()));
        
        customerDetailMapper.update(detail, new QueryWrapper<CustomerDetail>().eq("mian_id", model.getId()));

        // 6. 触发匹配存储过程
        clientCrmProjetDetailTypeMapper.callMatchingProcedure();
    }

    /**
     * 删除客户信息
     * <p>
     * 该方法实现以下功能：
     * 1. 根据ID查询并验证客户数据是否存在
     * 2. 执行逻辑删除（更新删除标记和时间）
     * 3. 触发客户项目匹配度重新评估
     * </p>
     *
     * @param id 客户主表ID
     * @throws IllegalArgumentException 当客户数据不存在时抛出
     * @author Jiejie
     */
    @Override
    public void del(Integer id) {
        CustomerMian model = customerMianMapper.selectOne(
                new QueryWrapper<CustomerMian>()
                        .eq("id", id)
                        .eq("is_delete", 0)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");

        model.setIsDelete(1);
        model.setDeleteTime(String.valueOf(System.currentTimeMillis() / 1000));
        customerMianMapper.updateById(model);

        // 调用存储过程
        clientCrmProjetDetailTypeMapper.callMatchingProcedure();
    }

    @Override
    public List<CustomerMianMatchingVo> matching(CustomerMianMatchingSearchValidate searchValidate) {
        // 1. 获取客户匹配的项目及其匹配次数
        List<Map<String, Object>> matchingResults = getCustomerProjectMatchingCounts(searchValidate.getId());
        log.debug("客户项目匹配结果: {}", matchingResults);
        
        // 2. 获取客户详情
        CustomerDetail customerDetail = getCustomerDetail(searchValidate.getId());
        
        // 3. 根据匹配次数评定项目星级
        List<CustomerMianMatchingVo> allMatchedProjects = evaluateProjectRatings(matchingResults, customerDetail);
        
        // 4. 根据筛选条件过滤结果
        List<CustomerMianMatchingVo> filteredProjects = filterProjectsByConditions(allMatchedProjects, searchValidate);
        
        // 5. 更新客户与项目的匹配记录
        updateCustomerProjectMatching(searchValidate.getId(), filteredProjects);
        
        return filteredProjects;
    }

    @Override
    public void editSalesman(CustomerMianUpdateValidate updateValidate) {

    }

    /**
     * 获取客户匹配的项目及其匹配次数
     * <p>
     * 该方法查询客户与项目的匹配记录，统计每个项目的匹配次数。
     * 只统计is_matching=1的有效匹配记录。
     * </p>
     * 
     * @param customerId 客户ID
     * @return List<Map<String, Object>> 项目匹配次数列表，包含project_id和ratingCount
     */
    private List<Map<String, Object>> getCustomerProjectMatchingCounts(Integer customerId) {
        QueryWrapper<TDeclarationMatching> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("customer_id", customerId)
                .eq("is_matching", 1)
                .select("project_id", "COUNT(*) AS ratingCount")
                .groupBy("project_id");
        return tDeclarationMatchingMapper.selectMaps(queryWrapper);
    }
    
    /**
     * 获取客户详情信息
     * 
     * @param customerId 客户ID
     * @return 客户详情
     */
    private CustomerDetail getCustomerDetail(Integer customerId) {
        QueryWrapper<CustomerDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.eq("mian_id", customerId);
        return customerDetailMapper.selectOne(detailQueryWrapper);
    }
    
    /**
     * 根据匹配次数评定项目星级
     * 
     * @param matchingResults 匹配结果
     * @param customerDetail 客户详情
     * @return 评定星级后的项目列表
     */
    private List<CustomerMianMatchingVo> evaluateProjectRatings(List<Map<String, Object>> matchingResults, 
                                                              CustomerDetail customerDetail) {
        List<CustomerMianMatchingVo> projectList = new ArrayList<>();
        Integer ratingFiveCount = 1;
        Integer ratingFourCount = 1;
        Integer ratingThreeCount = 1;
        
        for (Map<String, Object> matchResult : matchingResults) {
            // 获取项目详情
            Long projectId = Long.valueOf(matchResult.get("project_id").toString());
            ClientCrmProjetDetail projectDetail = getProjectDetail(projectId);
            if (projectDetail == null) {
                continue;
            }
            
            // 获取匹配次数
            Long matchCount = Long.valueOf(matchResult.get("ratingCount").toString());
            log.debug("项目[{}]星级配置: 三星={}, 四星={}, 五星={}, 匹配次数={}", 
                    projectId, projectDetail.getRatingThree(), projectDetail.getRatingFour(), 
                    projectDetail.getRatingFive(), matchCount);
            
            // 评定星级
            addProjectWithRating(projectList, projectDetail, matchCount, customerDetail, 
                    ratingThreeCount, ratingFourCount, ratingFiveCount);
        }
        
        return projectList;
    }
    
    /**
     * 获取项目详情
     * 
     * @param projectId 项目ID
     * @return 项目详情
     */
    private ClientCrmProjetDetail getProjectDetail(Long projectId) {
        ClientCrmProjetDetail projectDetail = clientCrmProjetDetailMapper.selectOne(
                new QueryWrapper<ClientCrmProjetDetail>()
                        .eq("id", projectId)
                        .last("limit 1"));
        
        if (projectDetail == null) {
            log.warn("项目ID[{}]数据不存在", projectId);
        }
        
        return projectDetail;
    }
    
    /**
     * 根据匹配次数将项目添加到列表并设置对应星级
     */
    private void addProjectWithRating(List<CustomerMianMatchingVo> projectList, 
                                     ClientCrmProjetDetail projectDetail, 
                                     Long matchCount, 
                                     CustomerDetail customerDetail,
                                     Integer ratingThreeCount,
                                     Integer ratingFourCount,
                                     Integer ratingFiveCount) {
        QueryWrapper<ClientCrmProjetDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", projectDetail.getId());
        
        // 检查项目是否满足各星级条件
        boolean hasThreeStar = projectDetail.getRatingThree() != null;
        boolean hasFourStar = projectDetail.getRatingFour() != null;
        boolean hasFiveStar = projectDetail.getRatingFive() != null;
        
        // 根据匹配次数判断星级
        ClientCrmProjetDetail projectInfo = clientCrmProjetDetailMapper.selectOne(queryWrapper);
        
        // 匹配三星条件
        if (hasThreeStar && matchCount >= Long.valueOf(projectDetail.getRatingThree()) 
                && (hasFourStar && matchCount < Long.valueOf(projectDetail.getRatingFour()))) {
            CustomerMianMatchingVo matchingVo = createMatchingVo(projectInfo, customerDetail, 3);
            matchingVo.setRatingThreeCount(ratingThreeCount++);
            projectList.add(matchingVo);
        }
        
        // 匹配四星条件
        if (hasFourStar && matchCount >= Long.valueOf(projectDetail.getRatingFour()) 
                && (hasFiveStar && matchCount < Long.valueOf(projectDetail.getRatingFive()))) {
            CustomerMianMatchingVo matchingVo = createMatchingVo(projectInfo, customerDetail, 4);
            matchingVo.setRatingFourCount(ratingFourCount++);
            projectList.add(matchingVo);
        }
        
        // 匹配五星条件
        if (hasFiveStar && matchCount >= Long.valueOf(projectDetail.getRatingFive())) {
            CustomerMianMatchingVo matchingVo = createMatchingVo(projectInfo, customerDetail, 5);
            matchingVo.setRatingFiveCount(ratingFiveCount++);
            projectList.add(matchingVo);
        }
        
        // 匹配两星条件（特殊情况）
        if (matchCount.equals(2L)) {
            CustomerMianMatchingVo matchingVo = createMatchingVo(projectInfo, customerDetail, 2);
            projectList.add(matchingVo);
        }
    }
    
    /**
     * 创建项目匹配结果对象
     * <p>
     * 将项目详情和客户详情信息组装成匹配结果对象，并设置匹配星级。
     * </p>
     * 
     * @param projectDetail 项目详情信息
     * @param customerDetail 客户详情信息
     * @param rating 匹配星级（2-5星）
     * @return CustomerMianMatchingVo 匹配结果对象
     */
    private CustomerMianMatchingVo createMatchingVo(ClientCrmProjetDetail projectDetail, 
                                                  CustomerDetail customerDetail, 
                                                  int rating) {
        CustomerMianMatchingVo matchingVo = new CustomerMianMatchingVo();
        BeanUtils.copyProperties(projectDetail, matchingVo);
        matchingVo.setDetail(customerDetail);
        matchingVo.setRating(rating);
        return matchingVo;
    }
    
    /**
     * 根据筛选条件过滤项目列表
     * 
     * @param allProjects 所有匹配的项目
     * @param searchValidate 搜索条件
     * @return 过滤后的项目列表
     */
    private List<CustomerMianMatchingVo> filterProjectsByConditions(List<CustomerMianMatchingVo> allProjects, 
                                                                 CustomerMianMatchingSearchValidate searchValidate) {
        // 如果没有筛选条件，直接返回所有项目
        if ((searchValidate.getSelectedRatings() == null || searchValidate.getSelectedRatings().isEmpty()) 
                && (searchValidate.getProjetName() == null || searchValidate.getProjetName().isEmpty())) {
            return allProjects;
        }
        
        // 根据星级筛选
        List<CustomerMianMatchingVo> filteredProjects = allProjects;
        if (searchValidate.getSelectedRatings() != null && !searchValidate.getSelectedRatings().isEmpty()) {
            filteredProjects = allProjects.stream()
                    .filter(project -> searchValidate.getSelectedRatings().contains(project.getRating()))
                    .collect(Collectors.toList());
        }
        
        // 根据项目名称筛选
        if (searchValidate.getProjetName() != null && !searchValidate.getProjetName().isEmpty()) {
            filteredProjects = filteredProjects.stream()
                    .filter(project -> project.getProjectName() != null && 
                            project.getProjectName().contains(searchValidate.getProjetName()))
                    .collect(Collectors.toList());
        }
        
        log.debug("筛选后的项目列表: {}", filteredProjects);
        return filteredProjects;
    }
    
    /**
     * 更新客户与项目的匹配记录
     * 
     * @param customerId 客户ID
     * @param filteredProjects 过滤后的项目列表
     */
    private void updateCustomerProjectMatching(Integer customerId, List<CustomerMianMatchingVo> filteredProjects) {
        List<Integer> projectIdList = filteredProjects.stream()
                .map(CustomerMianMatchingVo::getId)
                .collect(Collectors.toList());
        customerProjectService.add(customerId, projectIdList);
    }

}
